package com.ht.ui;

import com.ht.aems.eas.EasFacade;
import com.ht.aems.fesmodel.FesServer;
import com.ht.aems.ucp.UcpFacade;
import com.ht.dsp.DspFacade;
import com.ht.psplan.PlanCurveSender;
import hdservice.HdFacade;
import hhh.remoteService.jobManager.IJobManager;
import hhh.remoteService.utils.ServiceQuery;
import hhh.remoteService.utils.rmi.RmiRegistry;

import java.rmi.RemoteException;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: Dong Shufeng
 * Date: 11-12-22
 */
public class ServerManager {
    public static final String FES_SERVICE_ID = "fes";
    public static final String DSP_SERVICE_ID = "dsp";
    public static final String UCP_SERVICE_ID = "ucp";
    public static final String EAS_SERVICE_ID = "eas";
    public static final String PLAN_SERVICE_ID = "plan";
    public static final String JOB_SERVICE_ID = "JobManager";
    public static final String HD_SERVICE_ID = "hdservice";

    public static final String SERVER_NUMBER = "number";
    public static final String SERVER_NAME = "name";
    public static final String SERVER_IP = "ip";
    public static final String SERVER_PORT = "port";

    private Map<String, Integer> serviceNum;
    private Map<String, String> serviceDisplayName;
    private Map<String, String[]> serviceIp;
    private Map<String, Integer[]> servicePort;

    private UcpFacade ucpFacade;
    private DspFacade dspFacade;
    private EasFacade easFacade;
    private HdFacade hdFacade;

    private FesServer fesServer;
    private PlanCurveSender planSender;

    private IJobManager jobManager;
    private int currentJobManaerIndex;
    //private int currentJobManaerIndex;

    private List<String[]> notFoundServices;
    public static ServerManager instance = new ServerManager();

    private ServerManager() {
        ResourceBundle rb = ResourceBundle.getBundle("config.serverinfo");
        serviceNum = new HashMap<String, Integer>(5);
        serviceDisplayName = new HashMap<String, String>(5);
        serviceIp = new HashMap<String, String[]>(5);
        servicePort = new HashMap<String, Integer[]>(5);
        initialServer(rb, JOB_SERVICE_ID);

        initialServer(rb, DSP_SERVICE_ID);
        initialServer(rb, UCP_SERVICE_ID);
        initialServer(rb, EAS_SERVICE_ID);
        initialServer(rb, HD_SERVICE_ID);

        initialServer(rb, FES_SERVICE_ID);
        initialServer(rb, PLAN_SERVICE_ID);
    }

    private void initialServer(ResourceBundle rb, String serverId) {
        String key = serverId + "." + SERVER_NUMBER;
        if (rb.containsKey(key)) {
            int serverNumber = Integer.parseInt(rb.getString(key));
            String name = rb.getString(serverId + "." + rb.getString(serverId + "." + SERVER_NAME));
            serviceDisplayName.put(serverId, name);
            serviceNum.put(serverId, serverNumber);
            String[] ips = new String[serverNumber];
            Integer[] ports = new Integer[serverNumber];
            serviceIp.put(serverId, ips);
            for (int i = 1; i <= serverNumber; i++) {
                ips[i - 1] = rb.getString(serverId + "." + SERVER_IP + String.valueOf(i));
                String portKey = serverId + "." + SERVER_PORT + String.valueOf(i);
                if (rb.containsKey(portKey))
                    ports[i - 1] = Integer.parseInt(rb.getString(portKey));
            }
            if (ports.length > 0 && ports[0] != null)
                servicePort.put(serverId, ports);
        }
    }

    public void refresh() {
        List<Object[]> jobManagers = getServices(JOB_SERVICE_ID, IJobManager.class.getName());
        List<Object[]> dspFacades = getServices(DSP_SERVICE_ID, DspFacade.class.getName());
        List<Object[]> ucpFacades = getServices(UCP_SERVICE_ID, UcpFacade.class.getName());
        List<Object[]> easFacades = getServices(EAS_SERVICE_ID, EasFacade.class.getName());
        List<Object[]> hdFacades = getServices(HD_SERVICE_ID, HdFacade.class.getName());
        List<Object[]> fesServers = getServices(FES_SERVICE_ID, FesServer.class.getName());
        List<Object[]> planSenders = getServices(PLAN_SERVICE_ID, PlanCurveSender.class.getName());
        currentJobManaerIndex = -1;
        jobManager = null;
        ucpFacade = null;
        dspFacade = null;
        easFacade = null;
        hdFacade = null;
        fesServer = null;
        planSender = null;
        for (Object[] objs : jobManagers) {
            IJobManager manager = (IJobManager) objs[0];
            try {
                if (manager.isInitialized() && !manager.isInStandbyMode()) {
                    currentJobManaerIndex = (Integer) objs[1];
                    jobManager = (IJobManager) objs[0];
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        if (currentJobManaerIndex == -1) {
            //todo:warn message should be created
        } else {
            String mainServerIp = serviceIp.get(JOB_SERVICE_ID)[currentJobManaerIndex];
            for (Object[] objs : dspFacades)
                if (serviceIp.get(DSP_SERVICE_ID)[(Integer) objs[1]].equals(mainServerIp)) {
                    dspFacade = (DspFacade) objs[0];
                    break;
                }
            for (Object[] objs : ucpFacades)
                if (serviceIp.get(UCP_SERVICE_ID)[(Integer) objs[1]].equals(mainServerIp)) {
                    ucpFacade = (UcpFacade) objs[0];
                    break;
                }
            for (Object[] objs : easFacades)
                if (serviceIp.get(EAS_SERVICE_ID)[(Integer) objs[1]].equals(mainServerIp)) {
                    easFacade = (EasFacade) objs[0];
                    break;
                }
            for (Object[] objs : hdFacades)
                if (serviceIp.get(HD_SERVICE_ID)[(Integer) objs[1]].equals(mainServerIp)) {
                    hdFacade = (HdFacade) objs[0];
                    break;
                }
            //if (dspFacade != null) {
            //    try {
            //        Map map = SerializableUtil.createMap(dspFacade.getMemcachedConfig(), SerializableUtil.TYPE_STRING, SerializableUtil.TYPE_STRING);
            //        MemCachedConfigurator.reconfig(map);
            //    } catch (RemoteException e) {
            //        e.printStackTrace();
            //    }
            //}
            //if (ucpFacade != null) {
            //    try {
            //        String fesIp = ucpFacade.getCurrentFesIp();
            //        for (Object[] objs : fesServers)
            //            if (serviceIp.get(FES_SERVICE_ID)[(Integer) objs[1]].equals(fesIp)) {
            //                fesServer = (FesServer) objs[0];
            //                break;
            //            }
            //    } catch (RemoteException e) {
            //        e.printStackTrace();
            //    }
            //}
            if (planSenders.size() > 0)
                planSender = (PlanCurveSender) planSenders.get(0)[0];
        }
    }

    private List<Object[]> getServices(String serverId, String serviceName) {
        List<Object[]> services = new ArrayList<Object[]>(2);
        if (!serviceNum.containsKey(serverId) || serviceNum.get(serverId) < 1)
            return services;
        int num = serviceNum.get(serverId);
        for (int i = 0; i < num; i++) {
            String ip = serviceIp.get(serverId)[i];
            if (servicePort.containsKey(serverId)) {
                int port = servicePort.get(serverId)[i];
                Object obj = ServiceQuery.getService(ip, port, serviceName);
                if (obj == null) {
                    String[] service = new String[]{ip, serviceName};
                    notFoundServices.add(service);
                } else
                    services.add(new Object[]{obj, i});
            } else {
                Object obj = ServiceQuery.getService(ip, RmiRegistry.getRmiPort(), serviceName);
                if (obj == null) {
                    String[] service = new String[]{ip, serviceName};
                    notFoundServices.add(service);
                } else
                    services.add(new Object[]{obj, i});
            }
        }
        return services;
    }

    public DspFacade getDspFacade() {
        return dspFacade;
    }

    public EasFacade getEasFacade() {
        return easFacade;
    }

    public FesServer getFesServer() {
        return fesServer;
    }

    public HdFacade getHdFacade() {
        return hdFacade;
    }

    public List<String[]> getNotFoundServices() {
        return notFoundServices;
    }

    public IJobManager getJobManager() {
        return jobManager;
    }

    public PlanCurveSender getPlanSender() {
        return planSender;
    }

    public Map<String, String> getServiceDisplayName() {
        return serviceDisplayName;
    }

    public UcpFacade getUcpFacade() {
        return ucpFacade;
    }
}
